package br.mikhas.container.config;

import br.mikhas.util.Assert;

/**
 * An unresolved resource dependency
 * 
 * @author Mikhail Domanoski
 * 
 */
public abstract class UnresolvedDependency implements Dependency {

	/**
	 * Flags of theis dependency must be filled or its optional
	 */
	protected boolean required = true;

	/**
	 * The type of this dependency
	 */
	protected Class<?> type;

	/**
	 * How this dependency will be used by the resource
	 */
	private DependencyTarget destiny;

	private String property;

	/**
	 * Creates a new instance of {@link Dependency}
	 * 
	 * @param type
	 *            The java type of this dependency
	 * @param destiny
	 *            The {@link DependencyTarget} of this dependency
	 */
	public UnresolvedDependency(Class<?> type, DependencyTarget destiny) {
		Assert.notNull(type);
		Assert.notNull(destiny);
		this.type = type;
		this.destiny = destiny;
	}

	@Override
	public boolean isRequired() {
		return this.required;
	}

	public Class<?> getType() {
		return type;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == this)
			return true;
		if (obj instanceof Dependency) {
			Dependency dp = (Dependency) obj;
			return this.destiny.equals(dp.getTarget())
					&& this.type.equals(dp.getType())
					&& this.required == dp.isRequired();
		} else {
			return false;
		}

	}

	/**
	 * Defines either this dependency is stricly required or optional.
	 * <p>
	 * By default it is required.
	 * 
	 * @param required
	 *            If this dependency is required
	 */
	public void setRequired(boolean required) {
		this.required = required;
	}

	@Override
	public DependencyTarget getTarget() {
		return this.destiny;
	}

	@Override
	public String getPropertyName() {
		return this.property;
	}

	/**
	 * Sets the name of the property which this dependency will be injected
	 * 
	 * @param name
	 *            The name of the property.
	 *            <p>
	 *            If this dependency will be used as a constructor argument,
	 *            this name may be null.
	 */
	public void setPropertyName(String name) {
		this.property = name;
	}
}
